printing: Show all Avahi advertised printers
authorMarek Kasik <mkasik@redhat.com>
Fri, 5 Feb 2021 17:13:56 +0000 (18:13 +0100)
committerMarek Kasik <mkasik@redhat.com>
Fri, 5 Feb 2021 17:35:56 +0000 (18:35 +0100)
This commit unsubscribes CUPS backend from a DBus
signal in idle when listening for new items on Avahi.

Since GDBus emits gathered signals in idle while
checking whether the signal has been unsubscribed
it could happen that a signal was not processed
because it was removed from hash table of
subscribed signals.
This caused the situation where printers advertised
on Avahi were not listed in CUPS backend sometimes.

We need those signals since this happens when switching
from a general subscription which listens to signals
for all Avahi services to a specific one which listens
to just _ipp._tcp and _ipps._tcp (chicken and egg problem).

modules/printbackends/gtkprintbackendcups.c

index 3b24e3263f8d9bb2f78e1398afbb9ce08fe40232..6e69d66e3ce93711abcb683231a0b107b6bde0a9 100644 (file)
@@ -148,6 +148,7 @@ struct _GtkPrintBackendCups
   guint avahi_service_browser_subscription_ids[2];
   char *avahi_service_browser_paths[2];
   GCancellable *avahi_cancellable;
+  guint unsubscribe_general_subscription_id;
 
   gboolean      secrets_service_available;
   guint         secrets_service_watch_id;
@@ -1003,6 +1004,12 @@ gtk_print_backend_cups_dispose (GObject *object)
       backend_cups->avahi_service_browser_subscription_id = 0;
     }
 
+  if (backend_cups->unsubscribe_general_subscription_id > 0)
+    {
+      g_source_remove (backend_cups->unsubscribe_general_subscription_id);
+      backend_cups->unsubscribe_general_subscription_id = 0;
+    }
+
   backend_parent_class->dispose (object);
 }
 
@@ -3493,6 +3500,19 @@ avahi_service_browser_signal_handler (GDBusConnection *connection,
     }
 }
 
+static gboolean
+unsubscribe_general_subscription_cb (gpointer user_data)
+{
+  GtkPrintBackendCups *cups_backend = user_data;
+
+  g_dbus_connection_signal_unsubscribe (cups_backend->dbus_connection,
+                                        cups_backend->avahi_service_browser_subscription_id);
+  cups_backend->avahi_service_browser_subscription_id = 0;
+  cups_backend->unsubscribe_general_subscription_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
 static void
 avahi_service_browser_new_cb (GObject      *source_object,
                               GAsyncResult *res,
@@ -3534,9 +3554,10 @@ avahi_service_browser_new_cb (GObject      *source_object,
           cups_backend->avahi_service_browser_paths[1] &&
           cups_backend->avahi_service_browser_subscription_id > 0)
         {
-          g_dbus_connection_signal_unsubscribe (cups_backend->dbus_connection,
-                                                cups_backend->avahi_service_browser_subscription_id);
-          cups_backend->avahi_service_browser_subscription_id = 0;
+          /* We need to unsubscribe in idle since signals in queue destined for emit
+           * are emitted in idle and check whether the subscriber is still subscribed.
+           */
+          cups_backend->unsubscribe_general_subscription_id = g_idle_add (unsubscribe_general_subscription_cb, cups_backend);
         }
 
       g_variant_unref (output);